package BlackJack.View
{
	import BlackJack.Model.Events.LobbyEvent;
	import BlackJack.Model.Events.MessageEvent;
	import BlackJack.Model.Events.TableEvent;
	import BlackJack.Model.VO.DealPoker;
	import BlackJack.Model.VO.MultiClass;
	import BlackJack.Model.VO.Player;
	import BlackJack.Model.VO.RoleClass;
	import BlackJack.Model.VO.TableData;
	import caurina.transitions.Tweener;
	import com.adobe.protocols.dict.Dict;
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.utils.Dictionary;
	import flash.utils.clearTimeout;
	import flash.utils.setTimeout;

	public class Table extends Sprite
	{
		/**	顯示物件 */
		private var _display:MovieClip;
		/**	key為TableEvent的Events...value為各按鈕 */
		private var btnDict:Dictionary          = new Dictionary();
		/**	keyDict 為 btnDict 的Reverse */
		private var keyDict:Dictionary          = new Dictionary();
		private var roleDict:Dictionary         = new Dictionary();
		private var clipSetDict:Dictionary      = new Dictionary();
		public static const Banker:String       = 'Banker';
		public static const Player:String       = 'Player';
		public static const Player0:String      = 'Player0';
		public static const Player1:String      = 'Player1';
		public static const Player2:String      = 'Player2';
		public static const Player3:String      = 'Player3';
		public static const Player4:String      = 'Player4';
		public static const Roles:Array         = [Banker, Player0, Player1, Player2, Player3, Player4];
		public static const MaxPoint:String     = 'MaxPoint';
		public static const MinPoint:String     = 'MinPoint';
		public static const Index:String        = 'Index';
		public static const Infos:Array         = [MaxPoint, MinPoint, Index];
		public static const CheckOut:String     = 'CheckOut';
		public static const Select:String       = 'Select';
		public static const Bet:String          = 'Bet';
		public static const Ticker:String       = 'Ticker';
		public static const Wait:String         = 'Wait';
		public static const Messages:Array      = [CheckOut, Select, Bet, Ticker];
		public static const EventOptions:Array  = ['Total', 'Today', 'Win'];
		private var txtBet:TextField;
		private var txtBonus:TextField;
		private var pointBonus:MovieClip;
		private var _linkBonus:int;
		/**/
		private var tfDict:Dictionary           = new Dictionary();
		private var msgDict:Dictionary          = new Dictionary();
		/**/
		private var dealPool:Vector.<DealPoker> = Vector.<DealPoker>([]);
		/**/
		private var menu:MovieClip;
		/**	Coin Delay Time */
		public static const delay:Number        = 0.6;
		/**	金幣顯示(& 頁數) */
		private var pointBet:MovieClip;
		private var _totalBet:int;
		private var pointSubTotal:MovieClip;
		private var _subTotal:int;
		private var pointPlayer:MovieClip;
		private var _point:int;
		/**/
		private var _data:TableData;
		private var setDict:Dictionary;
		private var setPos:uint;
		private var setSplit:uint;
		/**/
		private var state:String;
		public static const Dealing:String      = 'Dealing';
		public static const ASK1:String         = 'ASK1';
		public static const ASK2:String         = 'ASK2';
		public var isDealing:Boolean;
		private var tableType:int;
		public var eventWindow:MovieClip;
		public var lastCount:MovieClip;
		public var isNonChangeBet:Boolean;
		public var _formDict:Dictionary;
		private var emotion:MovieClip;
		private var dictSmile:Dictionary        = new Dictionary();
		private var dictSmileCross:Dictionary   = new Dictionary();
		public static const Tab:String          = 'Tab';
		public static const Page:String         = 'Page';

		public function Table()
		{
		}

		public function get display():MovieClip
		{
			return _display;
		}

		public function set display(value:MovieClip):void
		{
			_display = value;
			addChild(value);
			var s:String;
			var btn:SimpleButton;
			var tf:TextField;
			var mc:MovieClip;
			var role:RoleClass;
			menu = value.Menu;
			var i:int;
			var j:int;
			var len:uint;
			emotion = value.oEmotionPanel;
			btn = emotion.btnClose;
			btn.focusRect = false;
			btn.addEventListener(MouseEvent.CLICK, smileHandler);
			for (i = 1; i <= 4; i++)
			{
				mc = emotion['oPage' + i];
				mc.visible = false;
				len = mc.numChildren;
				for (j = 0; j < len; j++)
				{
					var obj:Object = mc.getChildAt(j);
					if (obj is SimpleButton)
					{
						btn = obj as SimpleButton;
						btn.focusRect = false;
						btn.addEventListener(MouseEvent.CLICK, smileHandler);
					}
				}
				dictSmile[Page + i] = mc;
				btn = emotion['oTab' + i];
				btn.focusRect = false;
				btn.addEventListener(MouseEvent.CLICK, smileHandler);
				dictSmile[Tab + i] = btn;
				dictSmileCross[btn] = mc;
			}
			MovieClip(dictSmile[Page + 1]).visible = true;
			emotion.visible = false;
			for (i = 0; i < 3; i++)
			{
				mc = menu['ClipSet' + i];
				mc.visible = false;
				clipSetDict[i] = mc;
				for (j = 0; j < 3; j++)
				{
					btn = mc['Clip' + j];
					btn.focusRect = false;
					btn.addEventListener(MouseEvent.CLICK, clipHandler);
				}
			}
			for each (s in Roles)
			{
				mc = value.Message[s];
				msgDict[s] = mc;
				role = new RoleClass(s);
				roleDict[s] = role;
				role.msg = mc;
				role.setClip(value.TableClip[s]);
				role.setTip(value.Tip[s]);
				role.setModel(value.Model[s]);
				role.setArrow(value.Arrow[s]);
				role.setSubtotal(value.SubTotal[s]);
				role.setPoint(value.Point[s]);
				role.deal = value.Deal[s];
				role.setDealEnd(value.DealEnd[s]);
				role.setDeck(value.Deck[s]);
			}
			for each (s in TableEvent.Events)
			{
				btn = menu['btn' + s];
				btnDict[s] = btn;
				btn.addEventListener(MouseEvent.CLICK, btnHandler);
				btn.focusRect = false;
				keyDict[btn] = s;
			}
			for each (s in TableEvent.btnEvents)
			{
				btn = menu['btn' + s];
				btnDict[s] = btn;
				btn.addEventListener(MouseEvent.CLICK, btnHandler);
				btn.focusRect = false;
				keyDict[btn] = s;
			}
			for each (s in Infos)
			{
				tf = value.Info[s];
				tfDict[s] = tf;
				tf.focusRect = false;
				tf.defaultTextFormat = tf.getTextFormat();
				tf.text = '';
			}
			eventWindow = value.EventWindow;
			eventWindow.visible = false;
			lastCount = value.LastCount;
			lastCount.visible = false;
			for each (s in EventOptions)
			{
				tf = eventWindow[s];
				tfDict[s] = tf;
				tf.focusRect = false;
				tf.defaultTextFormat = tf.getTextFormat();
				tf.text = '';
			}
			for each (s in Messages)
			{
				mc = value.Message[s];
				msgDict[s] = mc;
			}
			pointBet = menu.PointBet;
			pointSubTotal = menu.PointSubTotal;
			pointPlayer = menu.PointPlayer;
			txtBet = value.BonusWindow.BetNumber;
			txtBonus = value.BonusWindow.BonusGet;
			pointBonus = value.BonusWindow.LinkBonus;
			txtBet.defaultTextFormat = txtBet.getTextFormat();
			txtBonus.defaultTextFormat = txtBonus.getTextFormat();
			txtBet.focusRect = false;
			txtBonus.focusRect = false;
			txtBet.text = '';
			txtBonus.text = '';
		}

		public function set data(value:TableData):void
		{
			Info(MaxPoint).text = value.MaxPoint.toString();
			Info(MinPoint).text = value.MinPoint.toString();
			Info(Index).text = value.Index.toString();
			var i:int;
			var j:int;
			var k:int;
			var len:int = value.Banker.length;
			for (i = 0; i < 5; i++)
			{
				if (value.ID[i].length > 0)
				{
					Role(Player + i).enable();
					Role(Player + i).txtName.text = value.Nickname[i];
					Role(Player + i).setModelNo(value.ModelNo[i]);
					Role(Player + i).txtAccount.text = value.ID[i];
				}
				else
				{
					Role(Player + i).disable();
				}
			}
			for (i = 0; i < len; i++)
			{
				Role(Banker).addPoker(value.Banker[i]);
			}
			for (i = 0; i < 5; i++)
			{
				len = value.Player[i][0].length;
				var len2:int = value.Player[i][1].length;
				if (len > 0 && len2 > 0)
				{
					Role(Player + i).setSplit(true);
				}
				for (k = 0; k < len; k++)
				{
					Role(Player + i).addPoker(value.Player[i][0][k]);
				}
				for (k = 0; k < len2; k++)
				{
					Role(Player + i).addPoker(value.Player[i][1][k]);
				}
			}
			_data = value;
		}

		public function set formDict(dict:Dictionary):void
		{
			_formDict = dict;
			for each (var s:String in Roles)
			{
				if (s != Banker)
				{
					delayDict(s);
				}
			}
		}

		private function delayDict(s:String):void
		{
			if (Role(s) == null)
			{
				setTimeout(delayDict, 500, s);
				return;
			}
			Role(s).form = _formDict;
		}

		public function get data():TableData
		{
			return _data;
		}

		public function set Color(value:int):void
		{
			tableType = value;
			MovieClip(display.Color).gotoAndStop('Type' + value);
			MovieClip(display.Color.Light).gotoAndStop('Pos' + data.spotLight);
			TotalBet = data.MinPoint;
			SubTotal = 0;
			menu.gotoAndStop(Wait);
			Btn(TableEvent.Exit).visible = true;
			Btn(TableEvent.BetMax).visible = false;
			Btn(TableEvent.BetMin).visible = false;
			Btn(TableEvent.Bet).visible = false;
			var mc:MovieClip;
			for each (mc in clipSetDict)
			{
				mc.visible = false;
			}
			for each (var s:String in Roles)
			{
				Role(s).clearClip();
			}
		}

		public function Info(value:String):TextField
		{
			return tfDict[value];
		}

		public function Msg(value:String):MovieClip
		{
			return msgDict[value];
		}

		public function Role(value:String):RoleClass
		{
			return roleDict[value];
		}

		private function smileHandler(event:MouseEvent):void
		{
			var btn:SimpleButton = event.currentTarget as SimpleButton;
			var name:String      = btn.name;
			switch (name)
			{
				case 'btnClose':
				{
					emotion.visible = false;
					break;
				}
				case 'oTab1':
				case 'oTab2':
				case 'oTab3':
				case 'oTab4':
				{
					for (var i:int = 1; i <= 4; i++)
					{
						MovieClip(dictSmile[Page + i]).visible = false;
					}
					MovieClip(dictSmileCross[btn]).visible = true;
					break;
				}
				default:
				{
					var key:String          = name.substr(0, 5);
					var serial:String       = name.replace(key, '');
					var nEvent:MessageEvent = new MessageEvent(key);
					nEvent.serial = serial;
					dispatchEvent(nEvent);
				}
			}
		}

		private function clipHandler(event:MouseEvent):void
		{
			var btn:SimpleButton = event.currentTarget as SimpleButton;
			var i:int            = int(btn.name.replace('Clip', ''));
			addBet(data.PlayerBet[i]);
		}

		public function quitGame():void
		{
			Msg(Ticker).gotoAndStop(1);
			clearTimeout(tid);
			clearGmae();
		}

		private function btnHandler(event:MouseEvent):void
		{
			var btn:SimpleButton  = event.currentTarget as SimpleButton;
			var type:String       = keyDict[btn];
			var nEvent:TableEvent = new TableEvent(type);
			dispatchEvent(nEvent);
		}

		public function tableHandler(event:TableEvent):void
		{
			switch (event.type)
			{
				case TableEvent.BetMax:
				{
					TotalBet = data.MaxPoint;
					break;
				}
				case TableEvent.BetMin:
				{
					TotalBet = data.MinPoint;
					break;
				}
				case TableEvent.Smile:
				{
					emotion.visible = !emotion.visible;
					break;
				}
				case TableEvent.Bet:
				{
					clearTimeout(tid);
					menu.gotoAndStop('BetEnd');
					MovieClip(clipSetDict[tableType]).visible = false;
					Btn(TableEvent.Exit).visible = false;
					Btn(TableEvent.BetMax).visible = false;
					Btn(TableEvent.BetMin).visible = false;
					Btn(TableEvent.Bet).visible = false;
					Msg(Bet).gotoAndStop(1);
					Msg(Ticker).gotoAndStop(1);
					break;
				}
				case TableEvent.Cancel:
				case TableEvent.Insurance:
				case TableEvent.Surrender:
				case TableEvent.Deal:
				{
					clearTimeout(tid);
					menu.gotoAndPlay('ASK1End');
					Msg(Bet).gotoAndStop(1);
					Msg(Ticker).gotoAndStop(1);
					break;
				}
				case TableEvent.Split:
				case TableEvent.Hit:
				case TableEvent.Stay:
				case TableEvent.Double:
				{
					clearTimeout(tid);
					menu.gotoAndPlay('ASK2End');
					Msg(Bet).gotoAndStop(1);
					Msg(Ticker).gotoAndStop(1);
					Role(Player + setPos).arrowTo(-1);
					break;
				}
			}
		}

		private function menuHandler(event:Event = null):void
		{
			menu.removeEventListener('ASKOK', menuHandler);
			var s:String;
			var bool:Boolean;
			for (s in setDict)
			{
				bool = setDict[s] == 1 ? true : false;
				Btn(s).visible = bool;
			}
			Msg(Select).gotoAndPlay('Start');
			Msg(Ticker).gotoAndPlay('Start');
			clearTimeout(tid);
			tid = setTimeout(autoDispatch, 5000);
		}

		private function playDeal():void
		{
			if (isDealing)
			{
				return;
			}
			if (dealPool.length == 0)
			{
				if (state == Dealing)
				{
					Socket(TableEvent.C2S_DealingOK);
				}
				return;
			}
			isDealing = true;
			var dp:DealPoker = dealPool.shift();
			Role(dp.target).deal.addEventListener('DealRoundOK', addPokerDealOK);
			Role(dp.target).dealPoker(dp.poker, dp.split);
		}

		private function addPokerDealOK(event:Event):void
		{
			var clip:MovieClip = event.currentTarget as MovieClip;
			clip.removeEventListener('DealRoundOK', addPokerDealOK);
			isDealing = false;
			setTimeout(playDeal, 150);
		}

		private function newGame():void
		{
			clearGmae();
			for each (var s:String in Roles)
			{
				Role(s).clearClip();
			}
			if (isNonChangeBet)
			{
				isNonChangeBet = false;
				TotalBet /= 2;
			}
			else
			{
				TotalBet = TotalBet;
			}
			Socket(TableEvent.C2S_CalculationOK);
		}
		private var tid:uint;

		public function clearGmae():void
		{
			for each (var s:String in Roles)
			{
				Role(s).clear();
				Role(s).arrowTo(-1);
			}
		}

		private function clearArrow():void
		{
			for each (var s:String in Roles)
			{
				Role(s).arrowTo(-1);
			}
		}

		private function autoDispatch():void
		{
			var btn:SimpleButton;
			switch (state)
			{
				case Bet:
				{
					clearGmae();
					btn = Btn(TableEvent.Bet);
					break;
				}
				case ASK1:
				{
					btn = Btn(TableEvent.Cancel);
					break;
				}
				case ASK2:
				{
					var p:uint = Role(Player + setPos).getPoint(setSplit);
					if (p > 16)
					{
						btn = Btn(TableEvent.Stay);
					}
					else
					{
						btn = Btn(TableEvent.Hit);
					}
					break;
				}
				case Dealing:
				{
					return;
				}
			}
			btn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
		}

		private function Btn(alias:String):SimpleButton
		{
			return btnDict[alias];
		}

		/**	要發送Socket指令均走這條 */
		private function Socket(type:String):void
		{
			var event:TableEvent;
			event = new TableEvent(type);
			dispatchEvent(event);
		}

		/**	Server傳送要求玩家下注指令 */
		public function S2C_PleaseBet():void
		{
			trace(this + '\t' + 'S2C_PleaseBet');
			newGame();
			state = Bet;
			menu.gotoAndStop(Bet);
			Btn(TableEvent.Exit).visible = true;
			Btn(TableEvent.BetMax).visible = true;
			Btn(TableEvent.BetMin).visible = true;
			Btn(TableEvent.Bet).visible = true;
			MovieClip(clipSetDict[tableType]).visible = true;
			/**	這邊把籌碼也打開 */
			Msg(Bet).gotoAndPlay('Start');
			Msg(Ticker).gotoAndPlay('Start');
			clearTimeout(tid);
			tid = setTimeout(autoDispatch, 5000);
		}

		/**	Server發送發牌資訊 */
		public function S2C_Dealing(BankPoker:uint, Poker1:Array, Poker2:Array, PokerPoint1:Array, PokerPoint2:Array):void
		{
			trace(this + '\t' + 'S2C_Dealing');
			state = Dealing;
			var dp:DealPoker;
			var i:int;
			for (i = 0; i < 5; i++)
			{
				if (Poker1[i] > 0)
				{
					dp = new DealPoker(Player + i, Poker1[i]);
					dealPool.push(dp);
				}
			}
			dp = new DealPoker(Banker, BankPoker);
			dealPool.push(dp);
			for (i = 0; i < 5; i++)
			{
				if (Poker2[i] > 0)
				{
					dp = new DealPoker('Player' + i, Poker2[i]);
					dealPool.push(dp);
				}
			}
			playDeal();
		}

		/**	玩家首輪詢問 */
		//public function S2C_PlayerAsk1(Deal:uint, Insurance:uint, Surrender:uint):void
		public function S2C_PlayerAsk1(dict:Dictionary):void
		{
			state = ASK1;
			setDict = dict;
			menu.addEventListener('ASKOK', menuHandler);
			menu.gotoAndPlay('ASK1');
		}

		/**	玩家二輪詢問 */
		//public function S2C_PlayerAsk2(Pos:uint, SplitNo:uint, Hit:uint, Stay:uint, Double:uint, Split:uint):void
		public function S2C_PlayerAsk2(dict:Dictionary, Pos:uint, SplitNo:uint):void
		{
			clearArrow();
			Role(Player + Pos).arrowTo(SplitNo);
			if (Pos != data.spotLight)
			{
				trace('ITS NOT MY ROUND');
				return;
			}
			setDict = dict;
			setPos = Pos;
			setSplit = SplitNo;
			menu.addEventListener('ASKOK', menuHandler);
			if (state == ASK2)
			{
				menu.gotoAndStop('ASK2Key');
				menuHandler();
			}
			else
			{
				state = ASK2;
				menu.gotoAndPlay('ASK2');
			}
		}
		private var dictCal:Dictionary;

		/**	牌局結算 */
		public function S2C_Calculation(Option:String):void
		{
			if (isDealing || dealPool.length > 0)
			{
				clearTimeout(tid);
				tid = setTimeout(S2C_Calculation, 1200, Option);
				return;
			}
			trace(this + '\t' + 'S2C_Calculation');
			trace(Option);
			clearArrow();
			dictCal = new Dictionary(true);
			var s:String;
			Msg(CheckOut).gotoAndPlay('Start');
			var array:Array = Option.split('\t');
			var temp:Array;
			var st:Array;
			var attr:String;
			var i:int;
			for (i = 0; i < array.length; i++)
			{
				s = array[i];
				temp = s.split('=');
				attr = temp[0];
				dictCal[attr] = new Vector.<int>(5);
				st = String(temp[1]).split(',');
				for (var j:int = 0; j < st.length; j++)
				{
					Vector.<int>(dictCal[attr])[j] = st[j];
				}
			}
			for (i = 0; i < 5; i++)
			{
				var h:int = 0;
				h += Vector.<int>(dictCal['H1'])[i];
				h += Vector.<int>(dictCal['H2'])[i];
				var p:int = 0;
				if (h > 0)
				{
					var p1:int = Vector.<int>(dictCal['P1'])[i];
					var p2:int = Vector.<int>(dictCal['P2'])[i];
					p += p1;
					p += p2;
					setTimeout(Role(Player + i).setCalculation, 1300, p1, p2);
					setTimeout(Role(Player + i).delaySubtotal, 1000, p);
					if (i == data.spotLight)
					{
						setTimeout(delaySubTotal, 1800, Vector.<int>(dictCal['S'])[i]);
						setTimeout(delayPoint, 1800, Vector.<int>(dictCal['T'])[i]);
					}
				}
			}
			setTimeout(newGame, 3500);
		/** int m_HsData[5][2];   //[第幾家][分門]有結算資料嗎? 0:無 1:有
		 int m_Point[5][2];    //[第幾家][分門]勝負金額不含本金
		 int m_SubTotal[5];    //小計
		 int m_TotalPoint[5];  //總資產
		 */
		}
		private var subtotalData:Vector.<uint>  = Vector.<uint>([]);

		/**	小計 */
		public function get SubTotal():int
		{
			return _subTotal;
		}

		public function set SubTotal(value:int):void
		{
			_subTotal = value;
			BlackJackMain.updateValue(pointSubTotal, value);
		}

		public function delaySubTotal(value:int):void
		{
			Tweener.addTween(this, {SubTotal: value, time: Table.delay});
		}

		/**	總彩金 */
		public function get Bonus():int
		{
			return _linkBonus;
		}

		public function set Bonus(value:int):void
		{
			_linkBonus = value;
			BlackJackMain.updateValue(pointBonus, value);
			if (tableType != 0)
			{
				txtBonus.text = Math.round(Bonus * TotalBet / 80000).toString();
			}
			else
			{
				txtBonus.text = ''
			}
		}

		public function delayBonus(value:int):void
		{
			Tweener.addTween(this, {Bonus: value, time: Table.delay});
		}

		/**	總下注 */
		public function get TotalBet():int
		{
			return _totalBet;
		}

		public function set TotalBet(value:int):void
		{
			_totalBet = value;
			BlackJackMain.updateValue(pointBet, value);
			if (isNonChangeBet)
			{
				return;
			}
			txtBet.text = value.toString();
			Role(Player + data.spotLight).Bet(value);
			if (tableType != 0)
			{
				txtBonus.text = Math.round(Bonus * value / 80000).toString();
			}
			else
			{
				txtBonus.text = '';
			}
		}

		public function delayBet(value:int):void
		{
			Tweener.addTween(this, {TotalBet: value, time: Table.delay});
		}

		public function addBet(value:int):void
		{
			value = Math.min(data.MaxPoint, TotalBet + value);
			TotalBet = value;
		}

		/**	玩家金幣 */
		public function get Point():int
		{
			return _point;
		}

		public function set Point(value:int):void
		{
			_point = value;
			BlackJackMain.updateValue(pointPlayer, value);
		}

		public function delayPoint(value:int):void
		{
			Tweener.addTween(this, {Point: value, time: Table.delay});
		}

		public function addDeal(dp:DealPoker):void
		{
			dealPool.push(dp);
			playDeal();
		}
	}
}
